home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / text / print / psutils.lha / psutils / psutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-06  |  8.8 KB  |  345 lines

  1. /* psutil.c
  2.  * Copyright (C) Angus J. C. Duggan 1991-1995
  3.  * See file LICENSE for details.
  4.  *
  5.  * utilities for PS programs
  6.  */
  7.  
  8. /*
  9.  *  AJCD 6/4/93
  10.  *    Changed to using ftell() and fseek() only (no length calculations)
  11.  *  Hunter Goatley    31-MAY-1993 23:33
  12.  *    Fixed VMS support.
  13.  *  Hunter Goatley     2-MAR-1993 14:41
  14.  *    Added VMS support.
  15.  */
  16. #include "psutil.h"
  17. #include "pserror.h"
  18. #include "patchlev.h"
  19.  
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23.  
  24. #define iscomment(x,y) (strncmp(x,y,strlen(y)) == 0)
  25.  
  26. extern char *program ;
  27. extern int pages;
  28. extern int verbose;
  29. extern FILE *infile;
  30. extern FILE *outfile;
  31. extern char pagelabel[BUFSIZ];
  32. extern int pageno;
  33.  
  34. static char buffer[BUFSIZ];
  35. static long bytes = 0;
  36. static long pagescmt = 0;
  37. static long headerpos = 0;
  38. static long endsetup = 0;
  39. static long beginprocset = 0;        /* start of pstops procset */
  40. static long endprocset = 0;
  41. static int outputpage = 0;
  42. static int maxpages = 100;
  43. static long *pageptr;
  44.  
  45. /* list of paper sizes supported */
  46. static Paper papersizes[] = {
  47.    { "a3", 842, 1191 },        /* 29.7cm * 42cm */
  48.    { "a4", 595, 842 },        /* 21cm * 29.7cm */
  49.    { "a5", 421, 595 },        /* 14.85cm * 21cm */
  50.    { "b5", 516, 729 },        /* 18.2cm * 25.72cm */
  51.    { "A3", 842, 1191 },        /* 29.7cm * 42cm */
  52.    { "A4", 595, 842 },        /* 21cm * 29.7cm */
  53.    { "A5", 421, 595 },        /* 14.85cm * 21cm */
  54.    { "B5", 516, 729 },        /* 18.2cm * 25.72cm */
  55.    { "letter", 612, 792 },    /* 8.5in * 11in */
  56.    { "legal", 612, 1008 },    /* 8.5in * 14in */
  57.    { "ledger", 1224, 792 },    /* 17in * 11in */
  58.    { "tabloid", 792, 1224 },    /* 11in * 17in */
  59.    { "statement", 396, 612 },    /* 5.5in * 8.5in */
  60.    { "executive", 540, 720 },    /* 7.6in * 10in */
  61.    { "folio", 612, 936 },    /* 8.5in * 13in */
  62.    { "quarto", 610, 780 },    /* 8.5in * 10.83in */
  63.    { "10x14", 720, 1008 },    /* 10in * 14in */
  64.    { NULL, 0, 0 }
  65. };
  66.  
  67. /* return pointer to paper size struct or NULL */
  68. Paper* findpaper(char *name)
  69. {
  70.    Paper *pp;
  71.    for (pp = papersizes; PaperName(pp); pp++) {
  72.       if (strcmp(PaperName(pp), name) == 0) {
  73.      return pp;
  74.       }
  75.    }
  76.    return (Paper *)NULL;
  77. }
  78.  
  79. /* Make a file seekable, using temporary files if necessary */
  80. FILE *seekable(FILE *fp)
  81. {
  82. #ifndef MSDOS
  83.   FILE *ft;
  84.   long r, w ;
  85. #endif
  86.   char *p;
  87.   char buffer[BUFSIZ] ;
  88. #if defined(WINNT)
  89.   struct _stat fs ;
  90. #else
  91.   long fpos;
  92. #endif
  93.  
  94. #if defined(WINNT)
  95.   if (_fstat(fileno(fp), &fs) == 0 && (fs.st_mode&_S_IFREG) != 0)
  96.     return (fp);
  97. #else
  98.   if ((fpos = ftell(fp)) >= 0)
  99.     if (!fseek(fp, 0L, SEEK_END) && !fseek(fp, fpos, SEEK_SET))
  100.       return (fp);
  101. #endif
  102.  
  103. #if defined(MSDOS)
  104.   message(FATAL, "input is not seekable\n");
  105.   return (NULL) ;
  106. #else
  107.   if ((ft = tmpfile()) == NULL)
  108.     return (NULL);
  109.  
  110.   while ((r = fread(p = buffer, sizeof(char), BUFSIZ, fp)) > 0) {
  111.     do {
  112.       if ((w = fwrite(p, sizeof(char), r, ft)) == 0)
  113.     return (NULL) ;
  114.       p += w ;
  115.       r -= w ;
  116.     } while (r > 0) ;
  117.   }
  118.  
  119.   if (!feof(fp))
  120.     return (NULL) ;
  121.  
  122.   /* discard the input file, and rewind the temporary */
  123.   (void) fclose(fp);
  124.   if (fseek(ft, 0L, SEEK_SET) != 0)
  125.     return (NULL) ;
  126.  
  127.   return (ft);
  128. #endif
  129. }
  130.  
  131.  
  132. /* copy input file from current position upto new position to output file */
  133. static int fcopy(long upto)
  134. {
  135.    long here = ftell(infile);
  136.    while (here < upto) {
  137.       if ((fgets(buffer, BUFSIZ, infile) == NULL) ||
  138.       (fputs(buffer, outfile) == EOF))
  139.      return(0);
  140.       here = ftell(infile);
  141.       bytes += strlen(buffer);
  142.    }
  143.    return (1);
  144. }
  145.  
  146. /* build array of pointers to start/end of pages */
  147. void scanpages(void)
  148. {
  149.    register char *comment = buffer+2;
  150.    register int nesting = 0;
  151.    register long int record;
  152.  
  153.    if ((pageptr = (long *)malloc(sizeof(long)*maxpages)) == NULL)
  154.       message(FATAL, "out of memory\n");
  155.    pages = 0;
  156.    fseek(infile, 0L, SEEK_SET);
  157.    while (record = ftell(infile), fgets(buffer, BUFSIZ, infile) != NULL)
  158.       if (*buffer == '%') {
  159.      if (buffer[1] == '%') {
  160.         if (nesting == 0 && iscomment(comment, "Page:")) {
  161.            if (pages >= maxpages-1) {
  162.           maxpages *= 2;
  163.           if ((pageptr = (long *)realloc((char *)pageptr,
  164.                          sizeof(long)*maxpages)) == NULL)
  165.              message(FATAL, "out of memory\n");
  166.            }
  167.            pageptr[pages++] = record;
  168.         } else if (headerpos == 0 && iscomment(comment, "Pages:"))
  169.            pagescmt = record;
  170.         else if (headerpos == 0 && iscomment(comment, "EndComments"))
  171.            headerpos = ftell(infile);
  172.         else if (iscomment(comment, "BeginDocument") ||
  173.              iscomment(comment, "BeginBinary") ||
  174.              iscomment(comment, "BeginFile"))
  175.            nesting++;
  176.         else if (iscomment(comment, "EndDocument") ||
  177.              iscomment(comment, "EndBinary") ||
  178.              iscomment(comment, "EndFile"))
  179.            nesting--;
  180.         else if (nesting == 0 && iscomment(comment, "EndSetup"))
  181.            endsetup = record;
  182.         else if (nesting == 0 && iscomment(comment, "BeginProlog"))
  183.            headerpos = ftell(infile);
  184.         else if (nesting == 0 &&
  185.                iscomment(comment, "BeginProcSet: PStoPS"))
  186.            beginprocset = record;
  187.         else if (beginprocset && !endprocset &&
  188.              iscomment(comment, "EndProcSet"))
  189.            endprocset = ftell(infile);
  190.         else if (nesting == 0 && (iscomment(comment, "Trailer") ||
  191.                       iscomment(comment, "EOF"))) {
  192.            fseek(infile, record, SEEK_SET);
  193.            break;
  194.         }
  195.      } else if (headerpos == 0 && buffer[1] != '!')
  196.         headerpos = record;
  197.       } else if (headerpos == 0)
  198.      headerpos = record;
  199.    pageptr[pages] = ftell(infile);
  200.    if (endsetup == 0 || endsetup > pageptr[0])
  201.       endsetup = pageptr[0];
  202. }
  203.  
  204. /* seek a particular page */
  205. void seekpage(int p)
  206. {
  207.    fseek(infile, pageptr[p], SEEK_SET);
  208.    if (fgets(buffer, BUFSIZ, infile) != NULL &&
  209.        iscomment(buffer, "%%Page:")) {
  210.       char *start, *end;
  211.       for (start = buffer+7; isspace(*start); start++);
  212.       if (*start == '(') {
  213.      int paren = 1;
  214.      for (end = start+1; paren > 0; end++)
  215.         switch (*end) {
  216.         case '\0':
  217.            message(FATAL, "Bad page label while seeking page %d\n", p);
  218.         case '(':
  219.            paren++;
  220.            break;
  221.         case ')':
  222.            paren--;
  223.            break;
  224.         }
  225.       } else
  226.      for (end = start; !isspace(*end); end++);
  227.       strncpy(pagelabel, start, end-start);
  228.       pagelabel[end-start] = '\0';
  229.       pageno = atoi(end);
  230.    } else
  231.       message(FATAL, "I/O error seeking page %d\n", p);
  232. }
  233.  
  234. /* Output routines. These all update the global variable bytes with the number
  235.  * of bytes written */
  236. void writestring(char *s)
  237. {
  238.    fputs(s, outfile);
  239.    bytes += strlen(s);
  240. }
  241.  
  242. /* write page comment */
  243. void writepageheader(char *label, int page)
  244. {
  245.    if (verbose)
  246.       message(LOG, "[%d] ", page);
  247.    sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
  248.    writestring(buffer);
  249. }
  250.  
  251. /* search for page setup */
  252. void writepagesetup(void)
  253. {
  254.    char buffer[BUFSIZ];
  255.    if (beginprocset) {
  256.       for (;;) {
  257.      if (fgets(buffer, BUFSIZ, infile) == NULL)
  258.         message(FATAL, "I/O error reading page setup %d\n", outputpage);
  259.      if (!strncmp(buffer, "PStoPSxform", 11))
  260.         break;
  261.      if (fputs(buffer, outfile) == EOF)
  262.         message(FATAL, "I/O error writing page setup %d\n", outputpage);
  263.      bytes += strlen(buffer);
  264.       }
  265.    }
  266. }
  267.  
  268. /* write the body of a page */
  269. void writepagebody(int p)
  270. {
  271.    if (!fcopy(pageptr[p+1]))
  272.       message(FATAL, "I/O error writing page %d\n", outputpage);
  273. }
  274.  
  275. /* write a whole page */
  276. void writepage(int p)
  277. {
  278.    seekpage(p);
  279.    writepageheader(pagelabel, p+1);
  280.    writepagebody(p);
  281. }
  282.  
  283. /* write from start of file to end of header comments */
  284. void writeheader(int p)
  285. {
  286.    fseek(infile, 0L, SEEK_SET);
  287.    if (pagescmt) {
  288.       if (!fcopy(pagescmt) || fgets(buffer, BUFSIZ, infile) == NULL)
  289.      message(FATAL, "I/O error in header\n");
  290.       sprintf(buffer, "%%%%Pages: %d 0\n", p);
  291.       writestring(buffer);
  292.    }
  293.    if (!fcopy(headerpos))
  294.       message(FATAL, "I/O error in header\n");
  295. }
  296.  
  297. /* write prologue to end of setup section excluding PStoPS procset */
  298. int writepartprolog(void)
  299. {
  300.    if (beginprocset && !fcopy(beginprocset))
  301.       message(FATAL, "I/O error in prologue\n");
  302.    if (endprocset)
  303.       fseek(infile, endprocset, SEEK_SET);
  304.    writeprolog();
  305.    return !beginprocset;
  306. }
  307.  
  308. /* write prologue up to end of setup section */
  309. void writeprolog(void)
  310. {
  311.    if (!fcopy(endsetup))
  312.       message(FATAL, "I/O error in prologue\n");
  313. }
  314.  
  315. /* write from end of setup to start of pages */
  316. void writesetup(void)
  317. {
  318.    if (!fcopy(pageptr[0]))
  319.       message(FATAL, "I/O error in prologue\n");
  320. }
  321.  
  322. /* write trailer */
  323. void writetrailer(void)
  324. {
  325.    fseek(infile, pageptr[pages], SEEK_SET);
  326.    while (fgets(buffer, BUFSIZ, infile) != NULL) {
  327.       writestring(buffer);
  328.    }
  329.    if (verbose)
  330.       message(LOG, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
  331. }
  332.  
  333. /* write a page with nothing on it */
  334. void writeemptypage(void)
  335. {
  336.    if (verbose)
  337.       message(LOG, "[*] ");
  338.    sprintf(buffer, "%%%%Page: * %d\n", ++outputpage);
  339.    writestring(buffer);
  340.    if (beginprocset)
  341.       writestring("PStoPSxform concat\n");
  342.    writestring("showpage\n");
  343. }
  344.  
  345.